demo: Add a search filter
authorMohammed Sadiq <sadiq@sadiqpk.org>
Sun, 12 Jul 2020 15:39:27 +0000 (21:09 +0530)
committerMohammed Sadiq <sadiq@sadiqpk.org>
Sun, 12 Jul 2020 16:49:40 +0000 (22:19 +0530)
demos/gtk-demo/main.c
demos/gtk-demo/main.ui

index 8b3979fc42e302c549bc4a78421a043d7f794269..11e7f0f1b6894aa0655797128db180059705a514 100644 (file)
@@ -18,6 +18,7 @@ static gchar *current_file = NULL;
 static GtkWidget *notebook;
 static GtkSingleSelection *selection;
 static GtkWidget *toplevel;
+static char **search_needle;
 
 typedef struct _GtkDemo GtkDemo;
 struct _GtkDemo
@@ -945,7 +946,18 @@ selection_cb (GtkSingleSelection *sel,
               gpointer            user_data)
 {
   GtkTreeListRow *row = gtk_single_selection_get_selected_item (sel);
-  GtkDemo *demo = gtk_tree_list_row_get_item (row);
+  GtkDemo *demo;
+
+  gtk_widget_set_sensitive (GTK_WIDGET (notebook), !!row);
+
+  if (!row)
+    {
+      gtk_window_set_title (GTK_WINDOW (toplevel), "No match");
+
+      return;
+    }
+
+  demo = gtk_tree_list_row_get_item (row);
 
   if (demo->filename)
     load_file (demo->name, demo->filename);
@@ -953,6 +965,57 @@ selection_cb (GtkSingleSelection *sel,
   gtk_window_set_title (GTK_WINDOW (toplevel), demo->title);
 }
 
+static gboolean
+demo_filter_by_name (GtkTreeListRow     *row,
+                     GtkFilterListModel *model)
+{
+  GtkDemo *demo;
+  guint i;
+
+  /* Show all items if search is empty */
+  if (!search_needle || !search_needle[0] || !*search_needle[0])
+    return TRUE;
+
+  g_assert (GTK_IS_TREE_LIST_ROW (row));
+  g_assert (GTK_IS_FILTER_LIST_MODEL (model));
+
+  demo = gtk_tree_list_row_get_item (row);
+  g_assert (GTK_IS_DEMO (demo));
+
+  /* Show only if the name maches every needle */
+  for (i = 0; search_needle[i]; i++)
+    {
+      if (!demo->title)
+        return FALSE;
+
+      if (g_str_match_string (search_needle[i], demo->title, TRUE))
+        continue;
+
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static void
+demo_search_changed_cb (GtkSearchEntry *entry,
+                        GtkFilter      *filter)
+{
+  const char *text;
+
+  g_assert (GTK_IS_SEARCH_ENTRY (entry));
+  g_assert (GTK_IS_FILTER (filter));
+
+  text = gtk_editable_get_text (GTK_EDITABLE (entry));
+
+  g_clear_pointer (&search_needle, g_strfreev);
+
+  if (text && *text)
+    search_needle = g_strsplit (text, " ", 0);
+
+  gtk_filter_changed (filter, GTK_FILTER_CHANGE_DIFFERENT);
+}
+
 static GListModel *
 create_demo_model (void)
 {
@@ -1013,7 +1076,9 @@ activate (GApplication *app)
   GtkBuilder *builder;
   GListModel *listmodel;
   GtkTreeListModel *treemodel;
-  GtkWidget *window, *listview;
+  GtkWidget *window, *listview, *search_entry;
+  GtkFilterListModel *filter_model;
+  GtkFilter *filter;
 
   static GActionEntry win_entries[] = {
     { "run", activate_run, NULL, NULL, NULL }
@@ -1042,7 +1107,13 @@ activate (GApplication *app)
                                        get_child_model,
                                        NULL,
                                        NULL);
-  selection = gtk_single_selection_new (G_LIST_MODEL (treemodel));
+  filter_model = gtk_filter_list_model_new (G_LIST_MODEL (treemodel), NULL);
+  filter = gtk_custom_filter_new ((GtkCustomFilterFunc)demo_filter_by_name, filter_model, NULL);
+  gtk_filter_list_model_set_filter (filter_model, filter);
+  search_entry = GTK_WIDGET (gtk_builder_get_object (builder, "search-entry"));
+  g_signal_connect (search_entry, "search-changed", G_CALLBACK (demo_search_changed_cb), filter);
+
+  selection = gtk_single_selection_new (G_LIST_MODEL (filter_model));
   g_signal_connect (selection, "notify::selected-item", G_CALLBACK (selection_cb), NULL);
   gtk_list_view_set_model (GTK_LIST_VIEW (listview), G_LIST_MODEL (selection));
 
index 4c8b80806f7fa9ec7b56dd37d3eb27b55b8b87b8..3d18e18bf398f2702994dbbc265d998c245f71d0 100644 (file)
             <property name="hscrollbar-policy">never</property>
             <property name="min-content-width">150</property>
             <child>
-              <object class="GtkListView" id="listview">
-                <property name="factory">
-                  <object class="GtkBuilderListItemFactory">
-                    <property name="resource">/ui/main-listitem.ui</property>
+              <object class="GtkBox">
+                <property name="width-request">220</property>
+                <property name="orientation">vertical</property>
+
+                <child>
+                  <object class="GtkSearchBar">
+                    <property name="search-mode-enabled">1</property>
+                    <child>
+                      <object class="GtkSearchEntry" id="search-entry"/>
+                    </child>
                   </object>
-                </property>
+                </child>
+
+                <child>
+                  <object class="GtkListView" id="listview">
+                    <property name="factory">
+                      <object class="GtkBuilderListItemFactory">
+                        <property name="resource">/ui/main-listitem.ui</property>
+                      </object>
+                    </property>
+                  </object>
+                </child>
+
               </object>
             </child>
           </object>